//
//  AppDelegate.m
//  LYAddToDesktop
//
//  Created by yoyo on 2021/4/14.
//  https://github.com/dlgenius/DLAddToDesktop.git


#import "AppDelegate.h"
#import "DDRSAWrapper.h"
#import <CommonCrypto/CommonCrypto.h>
#import <Security/Security.h>

@interface AppDelegate ()
{
    DDRSAWrapper *_wrapper;
    NSString *_cipherString;
    SecKeyRef _privateKeyRef;
    SecKeyRef _publicKey;
    NSString *_plainString;
}
@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    _wrapper = [DDRSAWrapper new];
    
    NSString* certPath = [[NSBundle mainBundle] pathForResource:@"ios_distribution" ofType:@"cer"];
    NSData* certData = [NSData dataWithContentsOfFile:certPath];
    SecCertificateRef cert;
    if( [certData length] ) {
        cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
        if( cert != NULL ) {
            CFStringRef certSummary = SecCertificateCopySubjectSummary(cert);
            NSString *summaryString = [[NSString alloc] initWithString:(__bridge NSString*)certSummary];
            NSLog(@"CERT SUMMARY: %@", summaryString);
            CFRelease(certSummary);
        } else {
            NSLog(@" *** ERROR *** trying to create the SSL certificate from data located at %@, but failed", certPath);
        }
    }
    
    [self configP12];
    
    return YES;
}
//Coolor04-14.mobileconfig
- (NSData *)getmobileconfig {
     NSString *path =  [[NSBundle mainBundle] pathForResource:@"Coolor04-15未签名" ofType:@"mobileconfig"];
    NSData *mobileData = [NSData dataWithContentsOfFile:path];
    _plainString = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    return mobileData;
}

- (void)dataToWriteFile:(NSString *)file data:(NSData *)data {
    
    [data writeToFile:file atomically:YES];
}

- (void)configP12
{
    _plainString = @"liyaming123423ffdsfdsfd";
//    NSData *plainData = [_plainString dataUsingEncoding:NSUTF8StringEncoding];
    NSData *plainData = [self getmobileconfig];
    NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"ios_distributionP12" ofType:@"p12"];
    NSData *p12Data = [NSData dataWithContentsOfFile:resourcePath];
    
    NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
    // 在 iOS 上， SecKeyRef 对象是一个密码学角度的抽象的密钥对象（也就是说它可以代表一个公钥、私钥或者某种对称加密的密钥
    // 改成你设置的密码
    [options setObject:@"123456" forKey:(id)kSecImportExportPassphrase];
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import((CFDataRef)p12Data, (CFDictionaryRef)options, &items);
    if (securityError == noErr && CFArrayGetCount(items) > 0) {
        // 获取一个 Identity 对象
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        // 获取私钥
        SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        securityError = SecIdentityCopyPrivateKey(identityApp, &_privateKeyRef);
        if (securityError != noErr) {
            _privateKeyRef = NULL;
        }
        NSLog(@"privateKeyRef:%@ \n", _privateKeyRef);
        // 获取一个 Trust 对象
        SecTrustRef trustRef = (SecTrustRef)CFDictionaryGetValue(identityDict, kSecImportItemTrust);
        // 获取公钥
        // publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(trustRef);
        _publicKey = SecTrustCopyPublicKey(trustRef);
        NSLog(@"publicKey:%@ \n", _publicKey);
        NSData *cipherData = [_wrapper encryptWithPrivateKey:_privateKeyRef plainData:plainData];
        _cipherString = [cipherData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        NSString *logText = [NSString stringWithFormat:@"SecKey 公钥加密：\n%@",_cipherString];
        
        NSData *signData = [self sha256WithRSA:plainData privateKey:_privateKeyRef];
        NSString *signString = [signData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        NSString *signLog = [NSString stringWithFormat:@"私钥签名：\n%@",signString];
        NSLog(@"%@ \n", signLog);
        
        BOOL yet = [self rsaSHA256VertifyingData:plainData withSignature:signData publicKey:_publicKey];
        NSLog(@"%d \n", yet);
    }
    CFRelease(items);
}

- (NSData *)sha256WithRSA:(NSData *)plainData privateKey:(SecKeyRef)privateKey {
    
    size_t signedHashBytesSize = SecKeyGetBlockSize(privateKey);
    uint8_t* signedHashBytes = malloc(signedHashBytesSize);
    memset(signedHashBytes, 0x0, signedHashBytesSize);
    
    size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
    uint8_t* hashBytes = malloc(hashBytesSize);
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
        return nil;
    }
    
    SecKeyRawSign(privateKey,
                  kSecPaddingPKCS1SHA256,
                  hashBytes,
                  hashBytesSize,
                  signedHashBytes,
                  &signedHashBytesSize);
    
    NSData* signedHash = [NSData dataWithBytes:signedHashBytes
                                        length:(NSUInteger)signedHashBytesSize];
    
    if (hashBytes)
        free(hashBytes);
    if (signedHashBytes)
        free(signedHashBytes);
    
    return signedHash;
}

- (BOOL)rsaSHA256VertifyingData:(NSData *)plainData withSignature:(NSData *)signature publicKey:(SecKeyRef)publicKey {
    size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);
    const void* signedHashBytes = [signature bytes];
    
    size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
    uint8_t* hashBytes = malloc(hashBytesSize);
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
        return NO;
    }
    
    OSStatus status = SecKeyRawVerify(publicKey,
                                      kSecPaddingPKCS1SHA256,
                                      hashBytes,
                                      hashBytesSize,
                                      signedHashBytes,
                                      signedHashBytesSize);
    
    return status == errSecSuccess;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (!_cipherString) {
        NSLog(@"无密文数据");
        return;
    }
    
    NSData *cipherData = [[NSData alloc] initWithBase64EncodedString:_cipherString options:NSDataBase64DecodingIgnoreUnknownCharacters];
     // NSData *plainData = [_wrapper decryptWithKey:_privateKeyRef cipherData:cipherData padding:kSecPaddingPKCS1];
    
    NSData *plainData = [_wrapper decryptWithPublicKey:_publicKey cipherData:cipherData];
    
    NSString *outputPlainString = [[NSString alloc] initWithData:plainData encoding:NSUTF8StringEncoding];
    NSLog(@"outputPlainString:%@",outputPlainString);
    NSString *logText;
    if ([outputPlainString isEqualToString:_plainString]) {
        logText = [NSString stringWithFormat:@"SecKey 私钥解密成功：\n%@",outputPlainString];
    } else {
        logText = [NSString stringWithFormat:@"SecKey 私钥解密失败"];
    }
    NSLog(@"%@", logText);

}

- (void)applicationWillResignActive:(UIApplication *)application {
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        
    }];

    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    
    return YES;
}

@end
